package com.hzjq.rxblast.ui

import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.view.KeyEvent
import android.view.View
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.LinearLayoutManager
import com.hzjq.core.Blast
import com.hzjq.core.bean.*
import com.hzjq.core.callback.Callback
import com.hzjq.core.callback.ProgressCallback
import com.hzjq.core.event.PioUnEnableEvent
import com.hzjq.rxblast.R
import com.hzjq.rxblast.adapter.RegisterAdapter
import com.hzjq.rxblast.event.BlastEvent
import com.hzjq.rxblast.event.LogEvent
import com.hzjq.rxblast.wiget.BlastProgressFormatter
import com.lxj.xpopup.XPopup
import com.lxj.xpopup.core.BasePopupView
import com.lxj.xpopup.impl.ConfirmPopupView
import com.lxj.xpopup.interfaces.OnConfirmListener
import com.lxj.xpopup.interfaces.SimpleCallback
import com.wxl.common.base.AbsActivity
import com.wxl.common.util.Toll
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.functions.Consumer
import io.reactivex.schedulers.Schedulers
import kotlinx.android.synthetic.main.activity_blast.*
import kotlinx.android.synthetic.main.activity_charge_layout.*
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import java.util.concurrent.TimeUnit

class BlastActivity : AbsActivity() {


    companion object {
        fun start(context: Context, maxDelay: Long, caps: ArrayList<ErrorCapEntity>) {
            val intent = Intent(context, BlastActivity::class.java)
            intent.putExtra("maxDelay", maxDelay)
            intent.putExtra("caps", caps)
            context.startActivity(intent)
        }
    }

    private var max = 30
    private var p = 0
    private var mDisposable: Disposable? = null
    private var pressTime = 0L
    private var pressState = arrayListOf(0, 0)
    private val mRegisterAdapter = RegisterAdapter(arrayListOf())
    private val caps = arrayListOf<ErrorCapEntity>()
    private var isBlastEnd = 0
    private var warnPopupView: ConfirmPopupView? = null
    private var maxDelay = 0L
    private var disposable: Disposable? = null
    private val errorCaps = arrayListOf<ErrorCapEntity>()

    override fun getCreateContentViewId(): Int {
        return R.layout.activity_blast
    }

    override fun onCreateViewChanged() {
        maxDelay = intent.getLongExtra("maxDelay", 0)
        caps.clear()
        caps.addAll(intent.getSerializableExtra("caps") as ArrayList<ErrorCapEntity>)
        blastErrorView.layoutManager = LinearLayoutManager(this)
        blastErrorView.adapter = mRegisterAdapter
        blastProgress.max = 30
        blastProgress.progress = 30
        blastProgress.setStartDegree(-90)
        blastProgress.setProgressStartColor(
            ContextCompat.getColor(
                this,
                android.R.color.holo_green_light
            )
        )
        blastProgress.setProgressEndColor(
            ContextCompat.getColor(
                this,
                android.R.color.holo_red_light
            )
        )
        blastProgress.setProgressFormatter(BlastProgressFormatter())
        blastProgress.setProgressTextSize(35f)
        startCountDown()
        setBlastBtn()
    }

    private fun startCountDown() {
        mDisposable = Observable.interval(1, 1, TimeUnit.SECONDS)
            .map {
                p++
                max - p
            }.observeOn(AndroidSchedulers.mainThread())
            .subscribeOn(Schedulers.newThread())
            .subscribe {
                if (it <= 0) {
                    mDisposable?.dispose()
                    Toll.toll("超时未起爆")
                    showWarn(false)
                }
                blastProgress.progress = it
            }
    }


    private fun onExit() {
        mDisposable?.dispose()
        val show = XPopup.Builder(this)
            .hasShadowBg(false)
            .asLoading("正在退出...")
            .show()
        closeElectric(show)
    }


    private fun closeElectric(pop: BasePopupView?) {
        Blast.getInstance().charge()
            .onCloseElectric(object : Callback<Boolean> {
                override fun onError(errorCode: ErrorResult) {
                    pop?.dismiss()
                    if (pop != null) {
                        Toll.toll("退出失败")
                    }
                }

                override fun onResult(t: Boolean) {
                    pop?.dismiss()
                    if (t) {
                        Blast.getInstance().blast().cancel()
                        if (pop != null) {
                            finish()
                        }
                    } else {
                        if (pop != null) {
                            Toll.toll("退出失败")
                        }
                    }
                }

                override fun onRetryCountChanged(
                    retryCount: Int,
                    action: String
                ) {

                }

            })
    }


    private fun setBlastBtn() {
        blastBtn1.setOnClickListener {
            blast(0)
        }
        blastBtn2.setOnClickListener {
            blast(1)
        }
        blastCancelBtn.setOnClickListener {
            onBackPressed()
        }
    }

    private fun blast(position: Int) {
        val time = System.currentTimeMillis()
        pressState[position] = 1
        if (time - pressTime > 500) {
            blastBtn1.postDelayed(Runnable {
                if (pressState[0] == 1 && pressState[1] == 1) {
                    return@Runnable
                }
                pressTime = 0
                pressState[0] = 0
                pressState[1] = 0
                Toll.toll("请同时按下两个起爆按钮")
            }, 500)
            pressTime = time
        } else {
            if (pressState[0] == 1 && pressState[1] == 1) {
                doBlast()
            } else {
                Toll.toll("请同时按下两个起爆按钮")
            }
        }
    }


    private fun doBlast() {
        Blast.getInstance().charge().cancel()
        EventBus.getDefault().post(LogEvent("开始起爆"))
        blastProgress.visibility = View.GONE
        blastProgressLayout.visibility = View.VISIBLE
        blastResultListViewLayout.visibility = View.GONE
        blastBtnLayout.visibility = View.GONE
        mDisposable?.dispose()
        isBlastEnd = 1
        Blast.getInstance().blast()
            .onBlast(maxDelay, object : ProgressCallback<CapProgressEntity> {
                override fun onError(errorCode: ErrorResult) {
                    isBlastEnd = 0
                    blastProgressAction.text = errorCode.errorAction
                    blastStatusIcon.setTextColor(
                        ContextCompat.getColor(
                            this@BlastActivity,
                            android.R.color.holo_red_light
                        )
                    )
                }

                override fun onProgressChanged(progress: Int, total: Int, action: String) {
                    blastProgressBar.progress = progress
                    blastProgressBar.max = total
                    blastProgressAction.text = "${action}..."
                }

                override fun onResult(t: CapProgressEntity) {
                    if(t.progress == 100) {
                        isBlastEnd = 2
                        blastStatusIcon.setTextColor(
                            ContextCompat.getColor(
                                this@BlastActivity,
                                android.R.color.holo_green_light
                            )
                        )
                        blastResultTip.text = "爆破完成"
                        showSuccessCap()
                    }
                }

                override fun onRetryCountChanged(retryCount: Int, action: String) {
                    blastProgressAction.text = "${action}(${retryCount}次)..."
                }

            }, Consumer<ErrorReadCapEntity> {
                if(it.caps[it.caps.size -1].isScanEnd) {
                    convertErrorCap(it)
                    isBlastEnd = 0
                }
            })
    }


    private fun convertErrorCap(result: ErrorReadCapEntity) {
        errorCaps.clear()
        disposable?.dispose()
        disposable = Observable.create<MutableList<ErrorCapEntity>>() {
            val temp = arrayListOf<String>()
            errorCaps.clear()
            result.errors.forEach {
                if(!temp.contains(it.cap!!.uid)){
                    temp.add(it.cap!!.uid)
                    errorCaps.add(it)
                }
            }
            temp.clear()
            it.onNext(errorCaps)
        }.subscribeOn(Schedulers.newThread())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe {
                blastStatusIcon.setTextColor(
                    ContextCompat.getColor(
                        this@BlastActivity,
                        android.R.color.holo_red_light
                    )
                )
                blastResultTip.text = "爆破失败"
                mRegisterAdapter.setNewInstance(it)
                blastResult.visibility = View.GONE
                blastProgress.visibility = View.GONE
                blastProgressLayout.visibility = View.GONE
                blastResultListViewLayout.visibility = View.VISIBLE
            }
    }


    @SuppressLint("CheckResult")
    private fun showSuccessCap() {
        blastProgressAction.text = "正在组装雷管信息..."
        val eventCaps = arrayListOf<CapEntity>()
        Observable.create<MutableList<CapEntity>> {
            caps.forEach {
                eventCaps.add(it.cap!!)
                it.errorCode = -1
            }
            it.onNext(eventCaps)
        }.subscribeOn(Schedulers.newThread())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe {
                blastResult.visibility = View.GONE
                blastProgress.visibility = View.GONE
                blastProgressLayout.visibility = View.GONE
                blastResultListViewLayout.visibility = View.VISIBLE
                val e = BlastEvent()
                e.caps.addAll(it)
                e.time = System.currentTimeMillis()
                EventBus.getDefault().post(e)
                mRegisterAdapter.setNewInstance(caps)
            }
    }

    override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
        if (keyCode == KeyEvent.KEYCODE_F1) {
            blastBtn1.performClick()
        }
        if (keyCode == KeyEvent.KEYCODE_F4) {
            blastBtn2.performClick()
        }
        return super.onKeyDown(keyCode, event)
    }


    override fun onBackClick(): Boolean {
        if (isBlastEnd == 0) {
            showWarn(true)
            return false
        } else if (isBlastEnd == 1) {
            Toll.toll("爆破中，请勿操作...")
            return false
        }
        return true
    }

    override fun onBackPressed() {
        if (isBlastEnd == 0) {
            showWarn(true)
        } else {
            if (isBlastEnd == 2) {
                super.onBackPressed()
            } else {
                Toll.toll("爆破中，请勿操作...")
            }
        }
    }


    private fun showWarn(isCancel: Boolean) {
        if (warnPopupView != null && warnPopupView!!.isShow) {
            if (!isCancel) {
                warnPopupView?.dismiss()
            } else {
                return
            }
        }
        if (!isCancel) {
            closeElectric(null)
        }
        warnPopupView = XPopup.Builder(this)
            .dismissOnTouchOutside(false)
            .dismissOnBackPressed(false)
            .setPopupCallback(object : SimpleCallback() {
                override fun onCreated() {
                    if (!isCancel) {
                        warnPopupView?.hideCancelBtn()
                    }
                }
            })
            .asConfirm(
                "警告", "${if (isCancel) "" else "已超时，"}雷管已充入高压，请按相关规定进行执行！", "取消", "确定",
                OnConfirmListener {
                    onExit()
                }, null, !isCancel
            ).show() as ConfirmPopupView
    }

    override fun getPageTitle(): String {
        return "雷管起爆"
    }

    override fun onDestroy() {
        super.onDestroy()
        disposable?.dispose()
        Blast.getInstance().blast().cancel()
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    fun onPioUnEnableEvent(e: PioUnEnableEvent){
        showPioUnEnablePop(this)
    }
}